/**
 * @(#)SimulatorApkdownloadServiceImpl.java 2017年2月28日
 * Copyright(C) 2015 ZHEXIN IT CO.,LTD. All rights reserved.
 */
package org.jsbd.boss.service.impl;

import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.jsbd.boss.common.redis.RedisClient;
import org.jsbd.boss.dao.ISimulatorUVConfigDAO;
import org.jsbd.boss.domian.SimulatorUVConfig;
import org.jsbd.boss.domian.SimulatorUVType;
import org.jsbd.boss.service.ISimulatorADService;
import org.jsbd.boss.service.ISimulatorHMService;
import org.jsbd.boss.service.ISimulatorUVService;
import org.jsbd.boss.util.CacheKey;
import org.jsbd.boss.util.TimeModelUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zhexinit.proxy.domain.HttpContext;
import com.zhexinit.proxy.domain.HttpProxyLog;
import com.zhexinit.proxy.domain.ProxyHost;
import com.zhexinit.proxy.util.HttpProxyUtils;
import com.zhexinit.proxy.util.ProxyHostUtils;

import edu.hziee.common.queue.DelayExecuteBuffer;

/**
 * TODO 请加入本类的说明
 * 
 * @author <a href="mailto:zhangbinghua@zhexinit.com" >zbh</a>
 * @version 1.0.0
 */
@Service
public class SimulatorUVServiceImpl implements ISimulatorUVService {
	public static final Logger LOGGER = LoggerFactory.getLogger(SimulatorUVServiceImpl.class);

	private static Random r = new Random();
	private static final String[] RELEASE = { "2.3.6", "4.0.4", "4.4.2", "4.2.1", "4.3", "4.4.4", "4.1.2", "4.1.1" };
	private static final String[] HSTYPE = { "vivo Y27", "SM-G5108", "HTC D816w", "MIU-H6", "gucci", "R823T",
			"R7Plusm", "HM NOTE 1LTETD", "SM-G3508I", "SM-G3508J", "R831T", "Lenovo A656", "SM-G9008V",
			"HUAWEI Y511-T00", "H30-U10", "Coolpad 5200S", "X905", "S39h", "Coolpad 5200", "ALE-TL00", "SHV-E210L",
			"CRAVE S1", "Lenovo A398t+", "S2", "GT-I8558", "HM 1S" };
	@Autowired
	private RedisClient redisClient;
	
	private static final int ONE_DAY = 60 * 60 * 24;
	@Autowired
	private DelayExecuteBuffer<HttpProxyLog> zxHttpProxyLogBuffer;
	@Autowired
	private ISimulatorUVConfigDAO simulatorUVConfigDAO;
	
	@Autowired
	private ISimulatorADService simulatorADService;
	@Autowired
	private ISimulatorHMService simulatorHMService;
	
	BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(20);
	ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 1, TimeUnit.SECONDS, queue,new ThreadPoolExecutor.AbortPolicy());

	@Override
	public void simulatorUV() throws Exception {
		List<SimulatorUVConfig> list = simulatorUVConfigDAO.getSimulatorUVConfigList();
		if (list != null && list.size() > 0) {
			for (final SimulatorUVConfig config : list) {
				if (checkdownloadCount(config)) {
					LOGGER.debug("{} 已经执行超过最大次数:{}", config.getUrl(), config.getCount());
					continue;
				}
				String type = config.getType();
				switch (type) {
				case SimulatorUVType.url:
					downloadByurl(config);
					break;
				case SimulatorUVType.ad:
					simulatorADService.simulatorAD(config);
					break;
				case SimulatorUVType.hm:
					simulatorHMService.simulatordownload(config);
					break;
				default:
					LOGGER.error("not found type:" + type);
				}
			}
		}
	}

	@Override
	public void saveSimulatorUVConfig(SimulatorUVConfig config) {
		simulatorUVConfigDAO.saveSimulatorUVConfig(config);
	}

	@Override
	public void abondeSimulatorUVConfig(String id) {
		simulatorUVConfigDAO.abandonSimulatorUVConfig(id);
	}

	@Override
	public void effectSimulatorUVConfig(String id) {
		simulatorUVConfigDAO.effectSimulatorUVConfig(id);

	}

	@Override
	public void updateSimulatorUVConfig(SimulatorUVConfig config) {
		simulatorUVConfigDAO.updateSimulatorUVConfig(config);

	}

	@Override
	public Map<String, Object> getApkConfigByPage(SimulatorUVConfig config) {
		Map<String, Object> result = simulatorUVConfigDAO.selectConfigPageListMap(config);
		List<SimulatorUVConfig> list = (List<SimulatorUVConfig>) result.get("rows");
		if(list!=null){
			for(SimulatorUVConfig simulatorUVConfig:list){
				Long execount = getExeCount(simulatorUVConfig);
				execount=execount==null?0:execount;
				simulatorUVConfig.setTaskNum(simulatorUVConfig.getCount()+"|"+execount);
			}
		}
		return result;

	}
	
	public void downloadByurl(final SimulatorUVConfig config) {
		for (int i = 0; i < config.threadnum; i++) {
			Runnable run = new Runnable() {
				@Override
				public void run() {
					String uvcountkey = getSuccessKey(config);
					String downloadurl = config.getUrl();
					download(downloadurl, "uvbyurl-id"+config.getId());
					redisClient.incrementBy(uvcountkey, 1, ONE_DAY);
					try {
						int sleeptime=config.getLimitTime();
						if(sleeptime<=0){
							sleeptime=500;
						}
						Thread.sleep(sleeptime);
					} catch (InterruptedException e) {
						LOGGER.error("InterruptedException:" , e);
					}
				}
			};
			try{
				executor.execute(run);
			}catch (Exception e) {
				LOGGER.error("executor Exception:" , e);
			}
		}
		
		
	}

	/**
	 * 
	 * checkdownloadCount:TODO 请描述该方法是做什么用途的
	 * @author <a href="mailto:zhangbinghua@zhexinit.com" >zbh</a>
	 * @param config
	 * @return
	 */
	private boolean checkdownloadCount(SimulatorUVConfig config) {
		Long counter = getExeCount(config);
		if (counter == null) {
			counter = 0L;
		}
		Calendar calendar = Calendar.getInstance();
		
		int currentBrushNum = config.getCount();
		if("1".equals(config.getIsLimit())){
			currentBrushNum = TimeModelUtils.genMaxNumByTime(config.getCount(), calendar.getTime());
		}
		
		String type = config.getType();
		switch (type) {
		case SimulatorUVType.url:
			return counter >= currentBrushNum;
		case SimulatorUVType.hm:
			return counter >= currentBrushNum;
		case SimulatorUVType.ad:
			boolean result = counter >= currentBrushNum;
			long banneradsize = redisClient.getZsetsize(CacheKey.YBAD_BANNER_DELAY_QUEUE);
			long adsize = redisClient.getZsetsize(CacheKey.YBAD_DELAY_QUEUE);
			Long minbanneradsize = redisClient.getLong(CacheKey.YBAD_BANNER_DELAY_QUEUE + "_MIN_BANNERADSIZE");
			Long maxbanneradsize = redisClient.getLong(CacheKey.YBAD_BANNER_DELAY_QUEUE + "_MAX_BANNERADSIZE");
			if (minbanneradsize==null || minbanneradsize <= 40) {
				minbanneradsize = 40L;
			}
			if (maxbanneradsize==null ||maxbanneradsize <= 100) {
				maxbanneradsize = 100L;
			}
			if (banneradsize <= minbanneradsize) {
				banneradsize = minbanneradsize;
			}
			long weight = adsize / banneradsize;
			return result || weight > 8 || banneradsize > maxbanneradsize;
		default:
			LOGGER.error("not found type:" + type);
			return false;
		}
		
	}
	
	public String getSuccessKey(SimulatorUVConfig config){
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		Calendar cal = Calendar.getInstance();
		String date = df.format(cal.getTime());
		String id = config.getId();
		String uvcountkey = CacheKey.UV_TASK + id + "_" + date;
		return uvcountkey;
	}
	
	public Long getExeCount(SimulatorUVConfig config){
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		Calendar cal = Calendar.getInstance();
		String date = df.format(cal.getTime());
		String id = config.getId();
		String uvcountkey = CacheKey.UV_TASK + id + "_" + date;
		return redisClient.getLong(uvcountkey);
	}
	
	
	public  void download(String downloadurl,String type){
		
		String release = getRelease();
		String hstype = getHstype();
		String build = getBuild();

		HttpContext httpContext = new HttpContext();
		httpContext.setOrderId(UUID.randomUUID().toString());
		httpContext.setProvinceId("-1");
		httpContext.setImsi(httpContext.getOrderId());
		httpContext.setBizType(type);
		httpContext.setStep(0);
		HttpProxyLog httpProxyLog = new HttpProxyLog();
		httpProxyLog.setHttpContext(httpContext);
		httpProxyLog.setUrl(downloadurl);
		Map<String, String> headerMap = new HashMap<String, String>();
		headerMap.put("Accept",		"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
		headerMap.put("Accept-Encoding", "gzip,deflate");
		headerMap.put("Accept-Language", "zh-CN,en-US;q=0.8");
		headerMap.put("Accept-Charset", "utf-8, iso-8859-1, utf-16, gb2312, gbk, *;q=0.7");
		headerMap.put("User-Agent", "Mozilla/5.0 (Linux; U; Android " + release + "; zh-cn; "+ hstype + " Build/" + build	+ ") AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30");

		httpProxyLog.setHeaderMap(headerMap);
		HttpProxyUtils.httpGet(httpProxyLog, zxHttpProxyLogBuffer, false);

		//httpDownload(httpProxyLog, zxHttpProxyLogBuffer, false);
	}
	
	public static String getRelease() {
		return RELEASE[r.nextInt(RELEASE.length)];
	}

	public static String getHstype() {
		return HSTYPE[r.nextInt(HSTYPE.length)];
	}

	public static String getBuild() {
		return UUID.randomUUID().toString().substring(0, 6).toUpperCase();
	}

	public static boolean httpDownload(HttpProxyLog httpProxyLog, DelayExecuteBuffer<HttpProxyLog> httpProxyLogBuffer,
			boolean https) {
		HttpContext httpContext = httpProxyLog.getHttpContext();
		String provinceId = httpContext.getProvinceId();
		String imsi = httpContext.getImsi();
		ProxyHost proxyHost = ProxyHostUtils.getProxyHost(imsi, provinceId, 5, httpProxyLog.getHttpContext().getBizType());
		httpProxyLog.setIpConnect(proxyHost.getIp());
		httpProxyLog.getHeaderMap().put("Ip", proxyHost.getIp());

		long t = System.currentTimeMillis();

		String url = httpProxyLog.getUrl();
		try {
			Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost.getAddress(), proxyHost.getPort()));
			URLConnection conn = new URL(url).openConnection(proxy);

			String release = getRelease();
			String hstype = getHstype();
			String build = getBuild();

			conn.setRequestProperty("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
			conn.setRequestProperty("Accept-Encoding", "gzip,deflate");
			conn.setRequestProperty("Accept-Language", "zh-CN,en-US;q=0.8");
			conn.setRequestProperty("Accept-Charset", "utf-8, iso-8859-1, utf-16, gb2312, gbk, *;q=0.7");
			conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Linux; U; Android " + release + "; zh-cn; " + hstype+ " Build/" + build + ") AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30");
			InputStream in = conn.getInputStream();
			//ByteArrayOutputStream out = new ByteArrayOutputStream();
			byte[] b = new byte[1024];
			int len = 0;
			if ((len = in.read(b)) > -1) {
				// out.write(b, 0, len);
				LOGGER.info("download success");
			}
			 //FileUtil.writeBytes("d:/"+UUID.randomUUID()+".apk", out.toByteArray());
			// httpGet.releaseConnection();
			in.close();
			// out.close();

		} catch (Exception e) {
			LOGGER.error("http 代理请求失败 [{}]", httpProxyLog, e);
			return false;
		} finally {
			long t1 = System.currentTimeMillis();
			httpProxyLog.setReadTime(t1 - t);
			httpProxyLogBuffer.add(httpProxyLog);
		}
		return true;
	}

}
